using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;

namespace GoodStuff
{
    /// <summary>
    /// Bindings: { label, value, min, max }
    /// </summary>
    public class GoodNumericUpDown : GoodControlBase, IGoodControl
    {
        IGoodConvertibleVariable _minimum;
        IGoodConvertibleVariable _maximum;
        IGoodConvertibleVariable _value;

        NumericUpDown _nud;
        Label _label;

        public override void Initialize()
        {
            _value = ParameterNumericVariable("Variable");
           // _value.ValueChanged += OnVariableChanged;

            Trace.WriteLine("Initializing GoodNumericUpDown " + _value.InstanceName);

            _maximum = ParameterNumericVariable("Maximum");
            if (_maximum != null)
                _maximum.ValueChanged += OnVariableChanged;
            _minimum = ParameterNumericVariable("Minimum");
            if (_minimum != null)
                _minimum.ValueChanged += OnVariableChanged;

            _nud = new NumericUpDown();
            _label = new Label();
            Panel panel = new Panel();
            _control = panel;

            _label.Text = ParameterText("Text");
            _label.TextAlign = ContentAlignment.MiddleRight;
            _label.Size = _label.PreferredSize;

            _nud.BeginInit();
            _nud.TextAlign = HorizontalAlignment.Right;
            _nud.Anchor = AnchorStyles.None;
            _nud.AutoSize = false;

            // BEGIN: cheezy code block
            Graphics g = _nud.CreateGraphics();
            int d = (int)Math.Pow(10, 5) - 1;
            SizeF t = g.MeasureString(d.ToString(), _nud.Font);
            _nud.Size = new Size((int)t.Width + 30, _nud.Height);
            // END: cheezy code ends here

            _label.Location = new Point(
                panel.Margin.Left,
                panel.Margin.Top + Math.Max(0, (_nud.Height - _label.Height) / 2));
            _nud.Location = new Point(
                _label.Right + panel.Padding.Horizontal,
                panel.Margin.Top + Math.Max(0, (_label.Height - _nud.Height) / 2));
            _nud.EndInit();
            //_nud.Update();
            panel.Size = new Size(
                _nud.Right + panel.Margin.Right,
                Math.Max(_label.Height, _nud.Height) + panel.Margin.Vertical);
            panel.Controls.Add(_label);
            panel.Controls.Add(_nud);

            UpdateValues();

            _nud.ValueChanged += OnControlValueChanged;

            base.Initialize();
        }

        private void OnControlValueChanged(object sender, EventArgs args)
        {
            _value.Set(_nud.Value);
        }

        protected void HandleSizeChanged(object sender, EventArgs args)
        {

            _nud.Size = new Size(
                _control.Size.Width - _control.Margin.Horizontal,
                _control.Size.Height - _control.Margin.Vertical);
            _nud.Location = new Point(
                _control.Margin.Left,
                _control.Margin.Top);
        }

        protected override void OnVariableChanged(object sender, EventArgs args)
        {
            if (_nud.InvokeRequired)
                _nud.Invoke(new UpdateDelegate(UpdateValues));
            else
                UpdateValues();
        }

        private delegate void UpdateDelegate();

        private void UpdateValues()
        {
            if (_minimum != null)
                _nud.Minimum = _minimum.ToInt32(null);
            else
                _nud.Minimum = 0;

            if (_maximum != null)
                _nud.Maximum = _maximum.ToInt32(null);
            else
                _nud.Maximum = Int32.MaxValue;

            _nud.Value = Math.Min(_nud.Maximum, Math.Max(_nud.Minimum, _value.ToInt32(null)));
        }
    }
}
